<template>
  <el-container class="layout-container">
    <el-aside :width="isCollapse ? '64px' : '220px'"
    :class="{'menu-white':menuTheme=='light','menu-dark':menuTheme=='dark'}"
     class="sidebar-container">
      <el-scrollbar>
        <div class="web-title">
          <img style="width: 30px; height: 30px;vertical-align: middle;margin-right: 4px;" src="/logo.png" alt="">
          <span v-show="!isCollapse">{{ webInfoStore?.webInfo?.site_name }}</span>
        </div>
        <el-menu :default-active="activeMenu" :router="false" unique-opened :collapse="isCollapse"
          @select="handleSelect" :collapse-transition="false">
          <el-sub-menu :index="r.path" v-for="r in routes" :key="r.path">
            <template #title>
              <el-icon :size="16">
                <component :is="r.meta.icon" />
              </el-icon>
              <span>{{ r.meta.title }}</span>
            </template>
            <el-menu-item :index="r.path + '/' + sub.path" v-for="sub in r.children" :key="sub.path">
              <el-icon :size="16">
                <component :is="sub.meta.icon" />
              </el-icon>
              {{ sub.meta.title }}
            </el-menu-item>
          </el-sub-menu>
        </el-menu>
      </el-scrollbar>
    </el-aside>
    <el-container>
      <el-header class="header-container">
        <div class="navbar">
          <div class="left-menu">
            <el-icon class="menu-icon" @click="toggleSidebar">
              <Expand v-if="isCollapse" />
              <Fold v-else />
            </el-icon>
            <el-breadcrumb separator="/">
              <transition-group name="breadcrumb" tag="span">
                <el-breadcrumb-item v-for="item in pathInfoTitle" :key="item.path" :to="{ path: item.path }">
                  {{ item.meta.title }}
                </el-breadcrumb-item>
              </transition-group>
            </el-breadcrumb>
          </div>
          <div class="right-menu">
            <el-button class="header-btn" circle @click="refreshPage">
              <el-icon>
                <Refresh />
              </el-icon>
            </el-button>
            <el-button class="header-btn" circle @click="toggleFullScreen">
              <el-icon>
                <FullScreen />
              </el-icon>
            </el-button>
            <el-dropdown>
              <div class="user-dropdown">
                <el-avatar :size="30" :src="userInfoStore.userInfo?.avatar">
                  <span>{{ userInfoStore.userInfo?.nickname.substring(0, 1)}}</span>
                </el-avatar>
                <span class="user-name">{{ userInfoStore.userInfo?.nickname }}</span>
              </div>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item @click="openProfileDialog">
                    <el-icon>
                      <User />
                    </el-icon>
                    个人信息
                  </el-dropdown-item>
                  <el-dropdown-item @click="openPasswordDialog">
                    <el-icon>
                      <Setting />
                    </el-icon>
                    修改密码
                  </el-dropdown-item>
                  <el-dropdown-item divided @click="handleLogout">
                    <el-icon>
                      <SwitchButton />
                    </el-icon>
                    退出登录
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </div>
      </el-header>
      <div class="tags-view">
        <template :key="item.path" v-for="(item, i) in tagsViewData">
          <div @click="router.push(item.path)" class="tags" :class="{ 'tags-active': activeMenu === item.path }">
            <el-icon :size="14">
              <component :is="item?.meta?.icon" />
            </el-icon>
            {{ item?.meta?.title || '-' }}<span @click.stop="closeTags(i)">×</span>
          </div>
        </template>
      </div>
      <el-main class="main-container">
        <Transition name="slide-fade">
          <router-view v-slot="{ Component }">
            <keep-alive :include="keepAliveComponents" :exclude="excludeKeepAliveComponents">
              <Component :is="Component" />
            </keep-alive>
          </router-view>
        </Transition>
        <div class="copyright">
          <div><span>{{ currentTime }}</span></div>
          <div>{{ webInfoStore?.webInfo?.copyright }}&nbsp;&nbsp;&nbsp;{{ webInfoStore?.webInfo?.icp }}</div>
        </div>
      </el-main>
    </el-container>
  </el-container>

  <!-- 个人信息弹窗 (仅展示) -->
  <el-dialog v-model="profileDialogVisible" title="个人信息" width="500px" :before-close="handleProfileClose">
    <el-descriptions :column="1" border>
      <el-descriptions-item label="用户名">
        {{ userInfoStore.userInfo?.username || '-' }}
      </el-descriptions-item>
      <el-descriptions-item label="昵称">
        {{ userInfoStore.userInfo?.nickname || '-' }}
      </el-descriptions-item>
      <el-descriptions-item label="手机号">
        {{ userInfoStore.userInfo?.phone || '-' }}
      </el-descriptions-item>
      <el-descriptions-item label="邮箱">
        {{ userInfoStore.userInfo?.email || '-' }}
      </el-descriptions-item>
      <el-descriptions-item label="角色">
        <el-tag v-for="role in userInfoStore.userInfo?.roles" :key="role" style="margin-right: 5px;">
          {{ role }}
        </el-tag>
      </el-descriptions-item>
    </el-descriptions>
    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="profileDialogVisible = false">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 修改密码弹窗 -->
  <el-dialog v-model="passwordDialogVisible" title="修改密码" width="500px" :before-close="handlePasswordClose">
    <el-form :model="passwordForm" label-width="100px" ref="passwordFormRef" :rules="passwordRules">
      <el-form-item label="当前密码" prop="oldPassword">
        <el-input v-model="passwordForm.oldPassword" type="password" show-password />
      </el-form-item>
      <el-form-item label="新密码" prop="newPassword">
        <el-input v-model="passwordForm.newPassword" type="password" show-password />
      </el-form-item>
      <el-form-item label="确认新密码" prop="confirmPassword">
        <el-input v-model="passwordForm.confirmPassword" type="password" show-password />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="passwordDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="updatePassword">保存</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { onBeforeUnmount, onBeforeMount, ref, watch, nextTick, reactive, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import {
  Expand,
  Fold,
  FullScreen,
  Refresh,
  Setting,
  SwitchButton,
  User,
} from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getRoutes } from "@/router/dynamicRoutes.ts";
import {
  setCacheObj,
  setCache,
  getCacheObj,
  existCache,
  clearAppCache,
  getCache
} from "@/utils/cache.ts";
import { logout, updateSelfPwd } from "@/api/system";
import { useUserInfoStore } from "@/stores/userInfo.ts";
import { useWebInfoStore } from "@/stores/webInfo.ts";

const route = useRoute()
const router = useRouter()
const userInfoStore = useUserInfoStore()
const webInfoStore = useWebInfoStore();
const routes: any[] = getRoutes()
const activeMenu = ref<string>('/dashboard')
const isCollapse = ref<boolean>(false)
const isFullScreen = ref<boolean>(false)
const pathInfoTitle = ref<any[]>([])
const tagsViewData = ref<any[]>([])
const keepAliveComponents = ref<string[]>([])
const excludeKeepAliveComponents = ref<string[]>([])
//menuTheme
const menuTheme = ref<string>('light')
// 个人信息弹窗相关
const profileDialogVisible = ref(false)

// 修改密码弹窗相关
const passwordDialogVisible = ref(false)
const passwordFormRef = ref()
const passwordForm = reactive({
  oldPassword: '',
  newPassword: '',
  confirmPassword: ''
})

const passwordRules = {
  oldPassword: [
    { required: true, message: '请输入当前密码', trigger: 'blur' }
  ],
  newPassword: [
    { required: true, message: '请输入新密码', trigger: 'blur' },
    { min: 3, message: '密码长度不能少于3位', trigger: 'blur' }
  ],
  confirmPassword: [
    { required: true, message: '请确认新密码', trigger: 'blur' },
    {
      validator: (rule: any, value: string, callback: any) => {
        if (value !== passwordForm.newPassword) {
          callback(new Error('两次输入的密码不一致'))
        } else {
          callback()
        }
      },
      trigger: 'blur'
    }
  ]
}

const cacheTagViews = () => {
  if (tagsViewData.value.length !== 0 && tagsViewData.value.length > 0) {
    // localStorage.setItem('tagsViewData', JSON.stringify(tagsViewData.value));
    setCacheObj('tagsViewData', tagsViewData.value)
  }
}
watch(isCollapse, (newVal) => {
  // localStorage.setItem('isCollapse', JSON.stringify({"isCollapse": newVal}))
  setCacheObj('isCollapse', { "isCollapse": newVal })
})
watch(tagsViewData, (newVal) => {
  if (tagsViewData.value.length !== 0 && tagsViewData.value.length > 0) {
    // localStorage.setItem('tagsViewData', JSON.stringify(newVal));
    setCacheObj('tagsViewData', newVal);
  }
}, {
  deep: true
})
//监听路由变化获取菜单active值
watch(
  () => route.path,
  (val) => {
    activeMenu.value = val
    // localStorage.setItem('currentRoute', val)
    setCache('currentRoute', val)
    cacheTagViews()
    pathInfoTitle.value = []
    route.matched.forEach((item) => {
      pathInfoTitle.value.push(item)
      let newTags = true;
      tagsViewData.value.forEach((item) => {
        if (item.path === val) {
          newTags = false;
          return
        }
      })
      if (newTags) {
        if (item.children?.length <= 0) {
          tagsViewData.value.push(item)
        }
      }
    })
    document.title = pathInfoTitle.value[pathInfoTitle.value.length - 1].meta.title;
  },
  { immediate: true }
)
onBeforeMount(() => {
  menuTheme.value = import.meta.env.VITE_MENU_THEME

  if (existCache('isCollapse')) {
    isCollapse.value = (getCacheObj('isCollapse') || {}).isCollapse;
  }
  if (existCache('currentRoute')) {
    activeMenu.value = getCache('currentRoute') || ''
  }
  if (existCache('tagsViewData')) {
    tagsViewData.value = getCacheObj('tagsViewData') as any[] || []
  }

  if (routes) {
    routes.forEach((item) => {
      if (item.children) {
        item.children.forEach((child) => {
          if (child.meta?.keepAlive && child?.name) {
            keepAliveComponents.value.push(child.name)
          }
        })
      }
    })
  }
})
onBeforeUnmount(() => {
})
const toggleSidebar = () => {
  isCollapse.value = !isCollapse.value
}
const refreshPage = () => {
  location.reload()
  ElMessage.success('页面刷新成功')
  // 实际项目中可以重新加载数据
}

const toggleFullScreen = () => {
  const element = document.documentElement
  if (!isFullScreen.value) {
    if (element.requestFullscreen) {
      element.requestFullscreen()
    }
    isFullScreen.value = true
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen()
    }
    isFullScreen.value = false
  }
}
const handleSelect = (index: string) => {
  router.push(index);
}

// 打开个人信息弹窗
const openProfileDialog = () => {
  profileDialogVisible.value = true
}

// 打开修改密码弹窗
const openPasswordDialog = () => {
  // 重置表单
  passwordForm.oldPassword = ''
  passwordForm.newPassword = ''
  passwordForm.confirmPassword = ''
  passwordDialogVisible.value = true
}

// 关闭个人信息弹窗
const handleProfileClose = () => {
  profileDialogVisible.value = false
}

// 关闭修改密码弹窗
const handlePasswordClose = () => {
  passwordDialogVisible.value = false
}

// 更新密码
const updatePassword = () => {
  if (!passwordFormRef.value) return

  passwordFormRef.value.validate(async (valid: boolean) => {
    if (valid) {
      try {
        // 调用修改密码接口
        await updateSelfPwd({
          oldPassword: passwordForm.oldPassword,
          newPassword: passwordForm.newPassword
        })
        ElMessage.success('密码修改成功')
        passwordDialogVisible.value = false
      } catch (error) {
        console.error('密码修改失败:', error)
      }
    }
  })
}

const handleLogout = () => {
  ElMessageBox.confirm('确定要退出登录吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    await logout()
    //清理vuex
    userInfoStore.clearUserInfo();
    clearAppCache();
    ElMessage.success('退出登录成功')
    await router.push('/login');
  })
}

const closeTags = (index: number) => {
  if (tagsViewData.value.length > 1) {
    // 获取要关闭的组件名称
    const componentName = tagsViewData.value[index].name || tagsViewData.value[index].meta?.title;
    if (activeMenu.value === tagsViewData.value[index].path) {
      if (index === 0) {
        router.push(tagsViewData.value[index + 1].path)
      } else {
        router.push(tagsViewData.value[index - 1].path)
      }
    }
    tagsViewData.value.splice(index, 1);
    cacheTagViews()

    // 将组件添加到排除列表中以清除缓存
    if (componentName) {
      // 添加到排除列表
      if (!excludeKeepAliveComponents.value.includes(componentName as string)) {
        if (keepAliveComponents.value.includes(componentName as string)) {
          excludeKeepAliveComponents.value.push(componentName as string);
        }
      }

      // 在下一个tick中移除排除项，这样组件会被重新缓存
      nextTick(() => {
        const excludeIndex = excludeKeepAliveComponents.value.indexOf(componentName as string);
        if (excludeIndex > -1) {
          setTimeout(() => {
            excludeKeepAliveComponents.value.splice(excludeIndex, 1);
          }, 0)
        }
      });
    }
  }
}


// 添加时间相关的响应式数据
const currentTime = ref<string>('')
let timeInterval: number | null = null
// 格式化时间的函数
const formatTime = () => {
  const now = new Date()
  const year = now.getFullYear()
  const month = String(now.getMonth() + 1).padStart(2, '0')
  const day = String(now.getDate()).padStart(2, '0')
  const hours = String(now.getHours()).padStart(2, '0')
  const minutes = String(now.getMinutes()).padStart(2, '0')
  const seconds = String(now.getSeconds()).padStart(2, '0')
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
// 更新时间显示
const updateTime = () => {
  currentTime.value = formatTime()
}
// 在组件挂载时启动定时器
onMounted(() => {
  updateTime() // 立即显示时间
  timeInterval = window.setInterval(updateTime, 1000) as unknown as number
})
// 在组件销毁前清除定时器
onBeforeUnmount(() => {
  if (timeInterval) {
    clearInterval(timeInterval)
  }
})


</script>

<style scoped>
.layout-container {
  height: 100vh;
}

.layout-container .el-header {
  position: relative;
  background-color: #ffffff;
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
  z-index: 999;
  padding: 0;
}

.layout-container .el-aside {
  box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
  transition: width 0.28s;
  user-select: none;
}

.el-menu-item {
  color: #b6b6b6 !important;
}

.layout-container .el-menu {
  border-right: none;
  height: 100%;
}

.menu-white {
  background-color: rgb(255, 255, 255);
}

.menu-white .el-menu-item {
  background-color: #ffffff;
  color: #000000b3 !important;
}

.menu-white .web-title {
  background-color: rgb(255, 255, 255) !important;
  color: #000000b3;
}

.menu-white .el-sub-menu {
  background-color: #ffffff;
  color: #000000b3 !important;
}

.menu-white .el-menu-item.is-active {
  color: var(--el-color-primary) !important;
  background-color: transparent !important;
}

.menu-dark {
  background-color: rgb(0 21 41);
}

.menu-dark .el-menu-item {
  background-color: #0c2135 !important;
}

.menu-dark .web-title {
  background-color: rgb(0 21 41) !important;
}

.menu-dark ::v-deep(.el-sub-menu) {
  background-color: rgb(10, 30, 50);
  /* 调整子菜单背景色 */
  transition: background-color 0.3s;

  /* 增加过渡效果 */
  .el-sub-menu__title {
    color: #c0c0c0 !important;
    /* 提升默认文字可读性 */
  }

  .el-sub-menu__title:hover {
    background-color: rgb(20, 40, 60) !important;
    /* 悬停时背景色变化 */
    color: #ffffff !important;
  }
}

/* 增加点缀色 */
.menu-dark ::v-deep(.el-sub-menu__icon-arrow) {
  /* color: #1890ff !important; */
}

.el-menu-item.is-active {
  color: #ffffff !important;
  background-color: var(--el-color-primary) !important;
}

.layout-container .el-main {
  padding: 0;
  background-color: rgb(240, 242, 245);
}

.layout-container .toolbar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  right: 20px;
}

.header-container {
  height: 50px;
  line-height: 50px;
}

.web-title {
  height: 50px;
  line-height: 50px;
  /* background-color: rgb(0 21 41); */
  color: #ffffff;
  font-size: 14px;
  padding: 0 20px;
  text-align: center;
  overflow: hidden;
  font-weight: 600;
  font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
  vertical-align: middle;
}

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 100%;
  padding: 0 20px;
}

.left-menu {
  display: flex;
  align-items: center;
}

.menu-icon {
  font-size: 20px;
  cursor: pointer;
  margin-right: 20px;
}

.right-menu {
  display: flex;
  align-items: center;
}

.header-btn {
  margin-right: 10px;
}

.user-dropdown {
  display: flex;
  align-items: center;
  cursor: pointer;
  margin-left: 10px;
}

.user-name {
  margin-left: 8px;
  font-size: 14px;
}

.main-container {
  padding: 16px;
  box-sizing: border-box;
  height: calc(100% - 50px);
  overflow-x: hidden;
  margin: 0 0 36px 0;
}


.sidebar-container .el-menu-item,
.sidebar-container .el-sub-menu__title {
  height: 50px;
  line-height: 50px;
}

.sidebar-container .el-sub-menu .el-menu-item {
  min-width: 220px;
}

/* 添加过渡动画 */
.el-menu--collapse .el-menu-item span,
.el-menu--collapse .el-sub-menu .el-sub-menu__title span {
  display: none;
}

.el-menu--collapse .el-menu-item .el-icon,
.el-menu--collapse .el-sub-menu .el-sub-menu__title .el-icon {
  margin-right: 0;
}

.slide-fade-enter-active {
  transition: all 0.3s ease-out;
}

.slide-fade-leave-active {
  transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-fade-enter-from,
.slide-fade-leave-to {
  transform: translateX(20px);
  opacity: 0;
}

/* 面包屑过渡动画 */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
  transition: all 0.2s ease-out;
}

.breadcrumb-enter-from {
  opacity: 0;
  transform: translateX(10px);
}

.breadcrumb-leave-active {
  position: absolute;
}

.breadcrumb-leave-to {
  opacity: 0;
  transform: translateX(-10px);
}

.breadcrumb-move {
  transition: all 0.2s ease-out;
}

.tags-view {
  height: 50px;
  display: flex;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
  padding: 4px 10px;
  background-color: #ffffff;
  border-bottom: 1px solid #dcdfe6;
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
  z-index: 10;
}

.tags {
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  height: 26px;
  line-height: 26px;
  cursor: pointer;
  transition: all 0.3s ease-out;
  font-size: 13px;
  color: #495060;
  user-select: none;
  margin: 5px;
  border: 1px solid #d8dce5;
}

.tags:hover {
  background-color: #e1e5eb;
  color: var(--el-color-primary);
}


.tags span {
  display: inline-block;
  width: 16px;
  height: 16px;
  line-height: 16px;
  text-align: center;
  margin-left: 6px;
  font-size: 12px;
  border-radius: 50%;
  transition: all 0.3s ease-out;
}

.tags span:hover {
  background-color: rgba(0, 0, 0, 0.1);
  transform: scale(1.1);
}

.tags-active:hover {
  background-color: var(--el-color-primary);
  color: #ffffff;
}

.tags-active {
  background-color: var(--el-color-primary);
  color: #ffffff;
  border-color: var(--el-color-primary);
}

.copyright {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 36px;
  text-align: right;
  background-color: #f8f8f8;
  color: #666;
  font-size: 14px;
  border-top: 1px solid #e7e7e7;
  z-index: -1000;
  display: flex;
  justify-content: space-between;
  padding: 10px 20px 10px 240px;
}
</style>
